package com.happy3w.cmds.install;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.function.Function;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Component
public class JarInfoDetector {
    private final Map<String, GroupInfo> groupInfoMap;

    public JarInfoDetector(InstallConfig installConfig) {
        this.groupInfoMap = installConfig.getGroups().stream()
                .map(GroupInfo::from)
                .collect(Collectors.toMap(GroupInfo::getArtifact, Function.identity()));
    }

    public LibConfig detect(File jarFile) {
        return Stream.<Function<File, LibConfig>>of(this::detectByPom, this::detectByConfig)
                .map(func -> func.apply(jarFile))
                .filter(Objects::nonNull)
                .findFirst()
                .orElse(null);
    }

    private static final Pattern PATTERN = Pattern.compile(
            "^(.*?)-((?:\\d+[.\\-]?)+[a-zA-Z0-9]*)\\.jar$",
            Pattern.CASE_INSENSITIVE
    );

    public LibConfig detectByConfig(File jarFile) {
        String jarName = jarFile.getName();
        Matcher matcher = PATTERN.matcher(jarName);
        if (!matcher.matches()) {
            return null;
        }
        String artifactId = matcher.group(1);
        String version = matcher.group(2);
        GroupInfo groupInfo = groupInfoMap.get(artifactId);
        if (groupInfo == null) {
            return null;
        }
        return LibConfig.builder()
                .jarFile(jarName)
                .group(groupInfo.getGroup())
                .artifact(artifactId)
                .version(version)
                .build();
    }

    public LibConfig detectByPom(File jarFile) {
        try (JarFile jar = new JarFile(jarFile)) {
            // 查找META-INF/maven/**/*/pom.properties文件
            Optional<JarEntry> pomEntry = jar.stream()
                    .filter(entry -> entry.getName().startsWith("META-INF/maven/") &&
                            entry.getName().endsWith("/pom.properties"))
                    .findFirst();

            if (pomEntry.isEmpty()) {
                return null;
            }
            // 读取pom.properties内容
            Properties props = loadProperties(jar, pomEntry.get());

            // 提取必要的属性
            String groupId = props.getProperty("groupId");
            String artifactId = props.getProperty("artifactId");
            String version = props.getProperty("version");

            // 验证必要属性是否存在
            if (groupId != null && artifactId != null && version != null) {
                return LibConfig.builder()
                        .jarFile(jarFile.getName())
                        .group(groupId)
                        .artifact(artifactId)
                        .version(version)
                        .build();
            } else {
                throw new RuntimeException(jarFile.getAbsolutePath() + " (pom.properties不完整)");
            }
        } catch (IOException e) {
            throw new RuntimeException(jarFile.getAbsolutePath() + " (处理出错)");
        }
    }

    private static Properties loadProperties(JarFile jar, JarEntry jarEntry) throws IOException {
        Properties props = new Properties();
        try (InputStream is = jar.getInputStream(jarEntry)) {
            props.load(is);
        }
        return props;
    }

    @Getter
    @AllArgsConstructor
    private static class GroupInfo {
        private final String artifact;
        private final String group;


        // aspectjrt=org.aspectj
        public static GroupInfo from(String groupInfo) {
            String[] split = groupInfo.split("=");
            return new GroupInfo(split[0], split[1]);
        }
    }
}
